package com.sweetcircle.utils;


import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.sweetcircle.exception.BusinessException;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.mail.javamail.JavaMailSender;

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * @Author: Anan
 * @email: 2328791101@qq.com
 * @project_name: anan-bookkeeping
 * @time: 2023/6/2916:37
 */


public class AnanUtils {
    private static final Logger logger = LoggerFactory.getLogger(AnanUtils.class);

    private static final String ALGORITHMS = "AES/ECB/PKCS5Padding";
    @Resource
    RedisUtils<Object> redisUtils;
    @Resource
    private JavaMailSender javaMailSender;

    public static boolean verifyAdministrator(String email) {

        File file = new File(System.getProperty("user.dir") + File.separator + "file/admin/AdministratorInfo.json");

        if (!file.exists()) {

            try {
                file.createNewFile();
                String content = """
                        {
                          "name": "AdministratorInfo",
                          "remark": "管理员用户集合",
                          "email": [
                            "请在这里添加管理员邮箱"
                          ]
                        }
                        """;
                Files.writeString(Paths.get(file.getPath()), content);


            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }


        try {
            BufferedReader reader = new BufferedReader(new FileReader(file));
            StringBuilder content = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                content.append(line);
            }
            // 将读取的JSON字符串转换为Java对象，这里假设JSON内容是一个User对象
            JSONObject parse = JSONObject.parseObject(content.toString());
            if (parse == null) {
                logger.error("管理员信息文件不存在");
                return false;
            }
            JSONArray emails = parse.getJSONArray("email");
            return emails.contains(email);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }


    }

    public static String MD5Encryption(String source, String key) {
        // 1.判断 source 是否有效
        if (source == null || source.length() == 0) {
            // 2.如果不是有效的字符串抛出异常
            throw new RuntimeException("字符串不可为空");
        }
        try {
            source = source + key;
            // 3.获取 MessageDigest 对象
            MessageDigest messageDigest = MessageDigest.getInstance("md5");
            // 4.获取明文字符串对应的字节数组
            byte[] input = source.getBytes();
            //执行加密
            byte[] output = messageDigest.digest(input);
            // 6.创建 BigInteger 对象
            int signum = 1;
            BigInteger bigInteger = new BigInteger(signum, output);
            // 7.按照 16 进制将 bigInteger 的值转换为大写字符串
            int radix = 16;
            return bigInteger.toString(radix).toUpperCase();
        } catch (Exception e) {
            logger.error(e.getMessage());
            return null;
        }
    }

    public static String MD5Encryption(String source) {
        // 1.判断 source 是否有效
        return MD5Encryption(source, source);
    }

    /**
     * 打乱顺序
     *
     * @param str
     * @return
     */
    public static String DisruptSort(String str) {
        char[] arr = str.toCharArray();
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            int a = random.nextInt(arr.length);
            char temp = arr[i];
            arr[i] = arr[a];
            arr[a] = temp;
        }
        return new String(arr);
    }

    public static String getRandomNumber(Integer count) {
        return RandomStringUtils.random(count, false, true);
    }

    public static Integer getRandomNumber(int a, int b) {
        return ThreadLocalRandom.current().nextInt(a, b);
    }

    public static String getRandomString(Integer count) {
        return RandomStringUtils.random(count, true, true);
    }

    public static String getId() {
        String uuid = UUID.randomUUID().toString();
        return MD5Encryption(uuid);
    }

    public static void readFile(HttpServletResponse response, String fileName) {
        String projectPath = System.getProperty("user.dir");
        File filePath = new File(projectPath + "/file/");
        File file = new File(projectPath + "/file/" + fileName);
        String[] split = fileName.split("\\.");
        String fileSuffix = split[split.length - 1];
        if (containsElement(Constants.IMAGE_SUFFIX_LIST, fileSuffix)) {
            response.setContentType("image/" + fileSuffix);
            filePath = new File(projectPath + "/file/images/");
            file = new File(projectPath + "/file/images/" + fileName);
        }
        if (containsElement(Constants.VIDEO_SUFFIX_LIST, fileSuffix)) {
            response.setContentType("video/" + fileSuffix);
            filePath = new File(projectPath + "/file/video/");
            file = new File(projectPath + "/file/video/" + fileName);
        }

        if (!filePath.exists()) {
            boolean mkdirs = filePath.mkdirs();
            if (!mkdirs) {
                throw new BusinessException(400, "文件文件夹创建失败  请联系管理员创建项目file文件夹");
            }
        }

        if (!file.exists()) {
            throw new BusinessException(400, "文件不存在");
        }

        try {
            byte[] bytes1 = Files.readAllBytes(file.toPath());
            response.getOutputStream().write(bytes1);
        } catch (IOException e) {
            throw new BusinessException(400, "文件传输失败 请重试");
        }

    }

    public static void readAvatarFile(HttpServletResponse response, String userId, String fileName) {
        String projectPath = System.getProperty("user.dir");
        File filePath = new File(projectPath + "/file/images/avatar");
        File file = new File(filePath+ File.separator + userId + File.separator + fileName);
        String[] split = fileName.split("\\.");
        String fileSuffix = split[split.length - 1];
        response.setContentType("image/" + fileSuffix);

        if (!filePath.exists()) {
            boolean mkdirs = filePath.mkdirs();
            if (!mkdirs) {
                throw new BusinessException(400, "文件文件夹创建失败  请联系管理员创建项目file文件夹");
            }
        }
        if (!file.exists()) {
            file = new File(projectPath + "/file/images/avatar/default/user.png");
        }

        try {
            byte[] bytes1 = Files.readAllBytes(file.toPath());
            response.getOutputStream().write(bytes1);
        } catch (IOException e) {
            throw new BusinessException(400, "文件传输失败 请重试");
        }

    }

    //    public static String emailSend(String toEmail,String msg,File file ){
//
//
//        MailAccount account = new MailAccount();
//        account.setHost("smtp.qq.com");  // 设置邮件服务器的主机名为"smtp.qq.com"。这是QQ邮箱的SMTP服务器地址。
//        account.setPort(465);  // 设置邮件服务器的端口号为465。这是QQ邮箱的SMTP服务器端口号。
//        account.setAuth(true);  // 设置邮件服务器需要身份验证。这意味着发送邮件时需要提供正确的用户名和密码。
//        account.setFrom("2328791101@qq.com");  // 设置邮件的发件人地址为"2328791101@qq.com"。这是QQ邮箱的邮箱地址。
//        account.setUser("2328791101@qq.com");  // 设置邮件的发件人用户名为"Anan记账"。这是邮件发送时显示的发件人名称。
//        account.setPass("sjvtcqzfdnlrdjdh");  // 设置邮件的发件人密码为"sjvtcqzfdnlrdjdh"。这是QQ邮箱的授权码，用于身份验证。
//
//        account.setSslEnable(true);  // 使用SSL安全连接
//        //指定实现javax.net.SocketFactory接口的类的名称,这个类将被用于创建SMTP的套接字
//        account.setSocketFactoryClass("javax.net.ssl.SSLSocketFactory");
//        //如果设置为true,未能创建一个套接字使用指定的套接字工厂类将导致使用java.net.Socket创建的套接字类, 默认值为true
//        account.setSocketFactoryFallback(true);
//        // 指定的端口连接到在使用指定的套接字工厂。如果没有设置,将使用默认端口456
//        account.setSocketFactoryPort(465);
//
//        String title = "用户注册验证码";
//        String html = String.format("<h1>【Anan记账】温馨提示您正在进行邮箱账号注册，您的验证码是：%s，有效期为5分钟请尽快输入。</h1>", msg);;
//
//        if(file==null) {
//            return MailUtil.send(account, toEmail, title, html, false);
//        }else{
//            return MailUtil.send(account, toEmail, title, html, true, file);
//        }
//
//    }
//
//    public boolean sendCheckCode(String email) {
//        try {
//            String code = RandomStringUtils.random(5,false,true);
//            MimeMessage message = javaMailSender.createMimeMessage();
//            MimeMessageHelper helper = new MimeMessageHelper(message, true);
//            //邮件发件人
//            helper.setFrom("2328791101@qq.com");
//            //邮件收件人 1或多个
//            helper.setTo(email);
//            //邮件主题
//            helper.setSubject("用户注册验证码");
//            //邮件内容
//            helper.setText(String.format("【Anan记账】温馨提示您正在进行邮箱账号注册，您的验证码是：%s，有效期为5分钟请尽快输入。", code));
//            //邮件发送时间
//            helper.setSentDate(new Date());
//            // 发送邮件
//            javaMailSender.send(message);
//            logger.msg("用户 "+email + " 的验证码 "+ code +" 发送成功！");
//            redisUtils.put(email, code, 5 * 60L);
//            return true;
//        } catch (Exception e) {
//            logger.error("邮件发送失败! error:", e);
//            throw new BusinessException("邮件发送失败");
//        }
//    }
    public static boolean isEmpty(Object s) {
        if (s == null) {
            return true;
        }
        String str = s.toString();
        if (null == str || "".equals(str) || "null".equals(str) || "\u0000".equals(str)) {
            return true;
        } else if ("".equals(str.trim())) {
            return true;
        }
        return false;
    }

    /**
     * 加密
     *
     * @param content 内容
     * @param key     key
     * @return java.lang.String
     */
    public static String encrypt(String content, String key) {
        try {
            //获得密码的字节数组
            byte[] raw = key.getBytes();
            //根据密码生成AES密钥
            SecretKeySpec skey = new SecretKeySpec(raw, "AES");
            //根据指定算法ALGORITHM自成密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            //初始化密码器，第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作，第二个参数为生成的AES密钥
            cipher.init(Cipher.ENCRYPT_MODE, skey);
            //获取加密内容的字节数组(设置为utf-8)不然内容中如果有中文和英文混合中文就会解密为乱码
            byte[] byteContent = content.getBytes(StandardCharsets.UTF_8);
            //密码器加密数据
            byte[] encodeContent = cipher.doFinal(byteContent);
            //将加密后的数据转换为字符串返回
            return Base64.getEncoder().encodeToString(encodeContent);

        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 解密
     *
     * @param encryptStr 加密后的内容
     * @param decryptKey 解密key
     * @return java.lang.String
     */
    public static String decrypt(String encryptStr, String decryptKey) {
        try {
            //获得密码的字节数组
            byte[] raw = decryptKey.getBytes();
            //根据密码生成AES密钥
            SecretKeySpec skey = new SecretKeySpec(raw, "AES");
            //根据指定算法ALGORITHM自成密码器
            Cipher cipher = Cipher.getInstance(ALGORITHMS);
            //初始化密码器，第一个参数为加密(ENCRYPT_MODE)或者解密(DECRYPT_MODE)操作，第二个参数为生成的AES密钥
            cipher.init(Cipher.DECRYPT_MODE, skey);
            //把密文字符串转回密文字节数组
            byte[] encodeContent = Base64.getDecoder().decode(encryptStr);
            //密码器解密数据
            byte[] byteContent = cipher.doFinal(encodeContent);
            //将解密后的数据转换为字符串返回
            return new String(byteContent, StandardCharsets.UTF_8);
        } catch (Exception e) {
            logger.error("String : {} aes decrypt error", encryptStr);
            return null;
        }
    }

    public static String upperCaseFirstLetter(String field) {
        if (isEmpty(field)) {
            return field;
        }
        //如果第二个字母是大写，第一个字母不大写
        if (field.length() > 1 && Character.isUpperCase(field.charAt(1))) {
            return field;
        }
        return field.substring(0, 1).toUpperCase() + field.substring(1);
    }

    public static void checkParam(Object param) {
        try {
            Field[] fields = param.getClass().getDeclaredFields();
            boolean notEmpty = false;
            for (Field field : fields) {
                String methodName = "get" + upperCaseFirstLetter(field.getName());
                Method method = param.getClass().getMethod(methodName);
                Object object = method.invoke(param);
                if (object != null && object instanceof String && !isEmpty(object.toString())
                        || object != null && !(object instanceof String)) {
                    notEmpty = true;
                    break;
                }
            }
            if (!notEmpty) {
                throw new BusinessException("多参数更新，删除，必须有非空条件");
            }
        } catch (BusinessException e) {
            throw e;
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException("校验参数是否为空失败");
        }
    }

    /**
     * 判断数组中是否包含指定的字符串元素。
     *
     * @param array         要检查的字符串数组
     * @param elementToFind 要查找的字符串元素
     * @return 如果数组包含该元素则返回true，否则返回false
     */
    public static boolean containsElement(String[] array, String elementToFind) {
        for (String element : array) {
            if (element != null && element.equals(elementToFind)) {
                return true;
            }
        }
        return false;
    }

    public static <T, S> T copyBean(S source, Class<T> target) {
        try {
            T t = target.getDeclaredConstructor().newInstance();
            BeanUtils.copyProperties(source, t);
            return t;
        } catch (Exception e) {
            throw new BusinessException("bean copy error");
        }

    }

    public static void copyBean(Object source, Object target) {
        try {
            BeanUtils.copyProperties(source, target);
        } catch (Exception e) {
            throw new BusinessException("bean copy error");
        }

    }

    public static <T, S> List<T> copyListBean(List<S> sList, Class<T> classz) {
        try {
            List<T> list = new ArrayList<T>();
            for (S s : sList) {
                T t = classz.getDeclaredConstructor().newInstance();
                BeanUtils.copyProperties(s, t);
                list.add(t);
            }
            return list;
        } catch (Exception e) {
            throw new BusinessException("bean copy error");
        }

    }

    /**
     * 获取请求头中的token
     *
     * @param request HttpServletRequest
     */
    public static String getAuthorization(HttpServletRequest request) {
        String authorization = request.getHeader("Authorization");
        if (AnanUtils.isEmpty(authorization)) {
            throw new BusinessException(400, "请求异常！缺少 Authorization 请求头");
        }
        return authorization.replaceFirst("Bearer ", "");
    }

    public static void main(String[] args) {

        System.out.println(verifyAdministrator("admin@admin.com"));


        String uuid = UUID.randomUUID().toString();
        System.out.println(MD5Encryption(uuid));
        System.out.println(System.currentTimeMillis());
        System.out.println(DisruptSort(String.valueOf(System.currentTimeMillis())));
        System.out.println(encrypt("anan", "46053F08D4A8411C825CDF61885265E7"));
        System.out.println(decrypt("MvkGW9eGU/tK1Q+PAyeXIg==", "46053F08D4A8411C825CDF61885265E7"));

    }
}
